using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Gko.Utils
{
	/// <summary>
	/// <see cref="T:System.IntPtr"/> class extensions
	/// </summary>
	public static class IntPtrExtensions
	{
		/// <summary>
		/// Marshals data from an unmanaged block of memory to a newly allocated managed object of the specified type.
		/// </summary>
		/// <typeparam name="TStruct">The type of the struct.</typeparam>
		/// <param name="ptr">A pointer to an unmanaged block of memory.</param>
		/// <returns>A managed object containing the data pointed to by the ptr parameter.</returns>
		/// <exception cref="ArgumentNullException">Argument is null.</exception>
		public static TStruct ToStructure<TStruct>(this IntPtr ptr)
		{
			if(ptr.IsNull()) {
				throw new ArgumentNullException("ptr");
			}
			return (TStruct)Marshal.PtrToStructure(ptr, typeof(TStruct));
		}

		/// <summary>
		/// Frees memory previously allocated from the unmanaged memory of the process with System.Runtime.InteropServices.Marshal.AllocHGlobal(System.IntPtr).
		/// </summary>
		/// <param name="hglobal">The handle returned by the original matching call to System.Runtime.InteropServices.Marshal.AllocHGlobal(System.IntPtr).</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "hglobal")]
		public static void FreeHGlobal(this IntPtr hglobal)
		{
			Marshal.FreeHGlobal(hglobal);
		}

		/// <summary>
		/// Allocates a managed <see cref="T:System.String"/> and copies all characters up to the first null character from an unmanaged Unicode string into it.
		/// </summary>
		/// <param name="ptr">The address of the first character of the unmanaged string.</param>
		/// <returns>A managed string holding a copy of the native string if the value of the ptr parameter is not <c>null</c>; otherwise, this method returns <c>null</c></returns>
		public static String ToUnicodeString(this IntPtr ptr)
		{
			return Marshal.PtrToStringUni(ptr);
		}

		/// <summary>
		/// Copies a specified number of characters from a Unicode string stored in native heap to a managed <see cref="T:System.String"/>.
		/// </summary>
		/// <param name="ptr">The address of the first character of the unmanaged string.</param>
		/// <param name="length">The number of Unicode characters to copy.</param>
		/// <returns>A managed string that holds a copy of the native string if the value of the ptr parameter is not <c>null</c>; otherwise, this method returns <c>null</c></returns>
		public static String ToUnicodeString(this IntPtr ptr, int length)
		{
			return Marshal.PtrToStringUni(ptr, length);
		}
	}
}